<script setup lang="ts">
import { ref, reactive, h, onMounted } from "vue";
import { DynamicTable } from "@/components/DynamicTable";
import { PaginationConfig, TableColumn } from "@/components/DynamicTable/types";
import DynamicForm from "@/components/DynamicForm/index.vue";
import type { DynamicFormInstance } from "@/components/DynamicForm/types";
import { FormItemConfig } from "@/components/DynamicForm/types";
import { ElMessage, ElDialog, ElTag, ElProgress } from "element-plus";
import {
  queryJavaVulnerabilities,
  scanVulnerability,
  batchScanVulnerability,
  getScanResult,
} from "../servers";

const props = defineProps<{
  task: string;
}>();

const emit = defineEmits<{
  (e: "scan-complete"): void;
}>();

const pagination = reactive<PaginationConfig>({
  currentPage: 1,
  pageSize: 10,
  total: 0,
  pageSizes: [10, 20, 50, 100],
  layout: "total, sizes, prev, pager, next",
  background: true,
});

const vulnerabilityList = ref([]);
const loading = ref(false);
const searchFormRef = ref<DynamicFormInstance>();
const selectedRows = ref<any[]>([]);

const searchForm = reactive({
  keyword: "",
  tags: "",
  cve_id: "",
  severity: "",
  min_cvss: "",
  max_cvss: "",
});

const searchConfig: FormItemConfig[] = [
  {
    key: "keyword",
    name: "关键词",
    type: "input",
    placeholder: "搜索漏洞名称或描述",
    params: {
      clearable: true,
      style: { width: "200px" },
    },
  },
  {
    key: "cve_id",
    name: "CVE编号",
    type: "input",
    placeholder: "如: CVE-2021-44228",
    params: {
      clearable: true,
      style: { width: "200px" },
    },
  },
  {
    key: "severity",
    name: "严重性",
    type: "select",
    placeholder: "选择严重性",
    params: {
      clearable: true,
      style: { width: "200px" },
      showPlaceholder: false,
      options: [
        { label: "全部", value: "" },
        { label: "严重", value: "critical" },
        { label: "高危", value: "high" },
        { label: "中等", value: "medium" },
        { label: "低危", value: "low" },
        { label: "信息", value: "info" },
      ],
    },
  },
  {
    key: "tags",
    name: "标签",
    type: "input",
    placeholder: "如: java,rce",
    params: {
      clearable: true,
      style: { width: "200px" },
    },
  },
];

const columns = ref<TableColumn[]>([
  {
    label: "CVE ID",
    prop: "cve_id",
    width: 150,
    show: true,
    render: (row) => {
      return h(
        "a",
        {
          href: row.link,
          target: "_blank",
          style: "color: #409eff; text-decoration: none",
        },
        row.cve_id
      );
    },
  },
  {
    label: "漏洞名称",
    prop: "name",
    minWidth: 250,
    show: true,
  },
  {
    label: "严重性",
    prop: "severity",
    width: 120,
    show: true,
    render: (row) => {
      const severityMap = {
        critical: { text: "严重", type: "danger" },
        high: { text: "高危", type: "warning" },
        medium: { text: "中等", type: "success" },
        low: { text: "低危", type: "info" },
        info: { text: "信息", type: "" },
      };
      const item = severityMap[row.severity] || {
        text: row.severity,
        type: "",
      };
      return h(ElTag, { type: item.type, size: "small" }, () => item.text);
    },
  },
  {
    label: "CVSS评分",
    prop: "cvss_score",
    width: 100,
    show: true,
    render: (row) => {
      const score = row.cvss_score || 0;
      const color =
        score >= 9
          ? "#f56c6c"
          : score >= 7
          ? "#e6a23c"
          : score >= 4
          ? "#409eff"
          : "#67c23a";
      return h(
        "span",
        { style: `color: ${color}; font-weight: bold` },
        score.toFixed(1)
      );
    },
  },
  {
    label: "标签",
    prop: "tags",
    width: 200,
    show: true,
    render: (row) => {
      if (!row.tags) return "无";
      const tagList = row.tags.split(",");
      return h(
        "div",
        {},
        tagList.map((tag: string) =>
          h(
            ElTag,
            { key: tag, size: "small", style: "margin-right: 4px" },
            () => tag.trim()
          )
        )
      );
    },
  },
  {
    label: "操作",
    prop: "action",
    width: 180,
    show: true,
    slot: "action",
    fixed: "right",
  },
]);

const fetchVulnerabilities = async () => {
  loading.value = true;
  try {
    const params: any = {
      page: pagination.currentPage,
      per_page: pagination.pageSize,
      ...searchForm,
    };
    // 转换数字类型
    if (params.min_cvss) params.min_cvss = parseFloat(params.min_cvss);
    if (params.max_cvss) params.max_cvss = parseFloat(params.max_cvss);

    // 移除空值
    Object.keys(params).forEach((key) => {
      if (
        params[key] === "" ||
        params[key] === null ||
        params[key] === undefined
      ) {
        delete params[key];
      }
    });

    const { data } = await queryJavaVulnerabilities(params);
    vulnerabilityList.value = data.vulnerabilities || [];
    pagination.total = data.total || 0;
  } catch (error) {
    ElMessage.error("获取漏洞列表失败");
  } finally {
    loading.value = false;
  }
};

const handleSearch = (value: any) => {
  searchForm.keyword = value.keyword || "";
  searchForm.tags = value.tags || "";
  searchForm.cve_id = value.cve_id || "";
  searchForm.severity = value.severity || "";
  searchForm.min_cvss = value.min_cvss || "";
  searchForm.max_cvss = value.max_cvss || "";
  pagination.currentPage = 1;
  fetchVulnerabilities();
};

const handleSearchReset = () => {
  searchFormRef.value?.resetFields();
  searchForm.keyword = "";
  searchForm.tags = "";
  searchForm.cve_id = "";
  searchForm.severity = "";
  searchForm.min_cvss = "";
  searchForm.max_cvss = "";
  pagination.currentPage = 1;
  fetchVulnerabilities();
};

const handlePageChange = (page: number) => {
  pagination.currentPage = page;
  fetchVulnerabilities();
};

const handleSizeChange = (size: number) => {
  pagination.pageSize = size;
  pagination.currentPage = 1;
  fetchVulnerabilities();
};

// 扫描相关
const scanDialogVisible = ref(false);
const scanForm = reactive({
  vulnerability_id: null,
  vulnerability_name: "",
  target_url: "",
});

// 扫描结果
const resultDialogVisible = ref(false);
const scanResult = ref<any>(null);
const loadingResult = ref(false);

// 批量扫描
const batchScanDialogVisible = ref(false);
const batchScanForm = reactive({
  target_url: "",
});

const handleSelectionChange = (selection: any[]) => {
  selectedRows.value = selection;
};

const handleBatchScan = () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning("请先选择要扫描的漏洞");
    return;
  }
  batchScanForm.target_url = "";
  batchScanDialogVisible.value = true;
};

// 漏洞详情
const detailDialogVisible = ref(false);
const vulnerabilityDetail = ref<any>(null);

const handleViewDetail = (row: any) => {
  vulnerabilityDetail.value = row;
  detailDialogVisible.value = true;
};

const handleScan = (row: any) => {
  scanForm.vulnerability_id = row.vulnerability_id || row.id;
  scanForm.vulnerability_name = row.name;
  scanForm.target_url = "";
  scanDialogVisible.value = true;
};

// 提交单个扫描
const submitScan = async () => {
  if (!scanForm.target_url) {
    ElMessage.error("请输入目标URL");
    return;
  }
  try {
    await scanVulnerability(scanForm);
    ElMessage.success("扫描任务创建成功");
    scanDialogVisible.value = false;
    emit("scan-complete");
  } catch (error) {
    ElMessage.error("创建扫描任务失败");
  }
};

// 查看扫描结果
const handleViewResult = async (row: any) => {
  loadingResult.value = true;
  resultDialogVisible.value = true;
  try {
    const { data } = await getScanResult(row.task_id || row.id);
    scanResult.value = data;
  } catch (error) {
    ElMessage.error("获取扫描结果失败");
    resultDialogVisible.value = false;
  } finally {
    loadingResult.value = false;
  }
};

// 提交批量扫描
const submitBatchScan = async () => {
  if (!batchScanForm.target_url) {
    ElMessage.error("请输入目标URL");
    return;
  }
  try {
    const vulnerabilityIds = selectedRows.value.map(
      (row) => row.vulnerability_id || row.id
    );
    const params = {
      vulnerability_ids: vulnerabilityIds,
      target_url: batchScanForm.target_url,
    };
    await batchScanVulnerability(params);
    ElMessage.success("批量扫描任务创建成功");
    batchScanDialogVisible.value = false;
    selectedRows.value = [];
    emit("scan-complete");
  } catch (error: any) {
    ElMessage.error(error.message || "批量扫描失败");
  }
};

onMounted(() => {
  fetchVulnerabilities();
});
</script>

<template>
  <div>
    <!-- 搜索表单 -->
    <el-card shadow="never">
      <div class="search-form-container">
        <DynamicForm
          ref="searchFormRef"
          v-model="searchForm"
          :form-config="searchConfig"
          :gutter="16"
          label-width="80px"
          type="search"
          @search="handleSearch"
          @reset="handleSearchReset"
        />
      </div>
    </el-card>

    <div style="height: 10px"></div>

    <el-card>
      <DynamicTable
        :pagination="pagination"
        :columns="columns"
        :data="vulnerabilityList"
        :loading="loading"
        selection-type="multiple"
        row-key="id"
        @current-page-change="handlePageChange"
        @size-change="handleSizeChange"
        @selection-change="handleSelectionChange"
      >
        <template #toolbar-left>
          <el-button type="primary" @click="handleBatchScan"
            >批量扫描</el-button
          >
        </template>

        <template #action="{ row }">
          <el-button type="info" size="small" @click="handleViewDetail(row)"
            >详情</el-button
          >
          <el-button type="primary" size="small" @click="handleScan(row)">
            扫描</el-button
          >
        </template>
      </DynamicTable>
    </el-card>

    <!-- 扫描对话框 -->
    <el-dialog v-model="scanDialogVisible" title="漏洞扫描" width="500px">
      <el-form :model="scanForm" label-width="100px">
        <el-form-item label="漏洞ID">
          <span>{{ scanForm.vulnerability_id }}</span>
        </el-form-item>
        <el-form-item label="漏洞名称">
          <span>{{ scanForm.vulnerability_name }}</span>
        </el-form-item>
        <el-form-item label="目标URL" required>
          <el-input
            v-model="scanForm.target_url"
            placeholder="http://example.com"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="scanDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitScan">开始扫描</el-button>
      </template>
    </el-dialog>

    <!-- 批量扫描对话框 -->
    <el-dialog v-model="batchScanDialogVisible" title="批量扫描" width="500px">
      <el-form :model="batchScanForm" label-width="100px">
        <el-form-item label="已选择漏洞">
          <el-tag type="success" size="large">
            共 {{ selectedRows.length }} 个漏洞
          </el-tag>
        </el-form-item>
        <el-form-item label="目标URL" required>
          <el-input
            v-model="batchScanForm.target_url"
            placeholder="http://example.com"
          />
        </el-form-item>
        <el-form-item label="漏洞列表">
          <el-scrollbar max-height="200px">
            <div
              v-for="row in selectedRows"
              :key="row.id"
              class="selected-vuln"
            >
              <el-tag size="small" style="margin: 4px 0">
                {{ row.name }} ({{ row.cve_id }})
              </el-tag>
            </div>
          </el-scrollbar>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="batchScanDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitBatchScan">开始扫描</el-button>
      </template>
    </el-dialog>

    <!-- 漏洞详情对话框 -->
    <el-dialog
      v-model="detailDialogVisible"
      title="漏洞详情"
      width="800px"
      destroy-on-close
    >
      <el-descriptions
        v-if="vulnerabilityDetail"
        :column="2"
        border
        :title="vulnerabilityDetail.name"
      >
        <el-descriptions-item label="CVE ID" :span="2">
          <a
            :href="vulnerabilityDetail.link"
            target="_blank"
            style="color: #409eff"
          >
            {{ vulnerabilityDetail.cve_id }}
          </a>
        </el-descriptions-item>
        <el-descriptions-item label="漏洞ID">
          {{ vulnerabilityDetail.id }}
        </el-descriptions-item>
        <el-descriptions-item label="严重性">
          <el-tag
            :type="
              vulnerabilityDetail.severity === 'critical'
                ? 'danger'
                : vulnerabilityDetail.severity === 'high'
                ? 'warning'
                : 'success'
            "
            size="small"
          >
            {{
              vulnerabilityDetail.severity === "critical"
                ? "严重"
                : vulnerabilityDetail.severity === "high"
                ? "高危"
                : vulnerabilityDetail.severity === "medium"
                ? "中等"
                : vulnerabilityDetail.severity === "low"
                ? "低危"
                : "信息"
            }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="CVSS评分">
          <span
            :style="
              vulnerabilityDetail.cvss_score >= 9
                ? 'color: #f56c6c; font-weight: bold'
                : vulnerabilityDetail.cvss_score >= 7
                ? 'color: #e6a23c; font-weight: bold'
                : 'color: #409eff; font-weight: bold'
            "
          >
            {{ vulnerabilityDetail.cvss_score }}
          </span>
        </el-descriptions-item>
        <el-descriptions-item label="EPSS评分">
          <span style="color: #909399">
            {{
              vulnerabilityDetail.epss_score
                ? (vulnerabilityDetail.epss_score * 100).toFixed(2) + "%"
                : "N/A"
            }}
          </span>
        </el-descriptions-item>
        <el-descriptions-item label="CWE ID">
          {{ vulnerabilityDetail.cwe_id || "N/A" }}
        </el-descriptions-item>
        <el-descriptions-item label="POC文件" :span="2">
          <code>{{ vulnerabilityDetail.file_name }}</code>
        </el-descriptions-item>
        <el-descriptions-item label="标签" :span="2">
          <el-tag
            v-for="tag in vulnerabilityDetail.tags?.split(',') || []"
            :key="tag"
            size="small"
            style="margin-right: 4px"
          >
            {{ tag.trim() }}
          </el-tag>
          <span v-if="!vulnerabilityDetail.tags">无</span>
        </el-descriptions-item>
        <el-descriptions-item label="漏洞描述" :span="2">
          {{ vulnerabilityDetail.description || "暂无描述" }}
        </el-descriptions-item>
        <el-descriptions-item label="修复建议" :span="2">
          <div style="white-space: pre-wrap">
            {{ vulnerabilityDetail.fix_suggestion || "暂无修复建议" }}
          </div>
        </el-descriptions-item>
        <el-descriptions-item label="参考链接" :span="2">
          <a
            :href="vulnerabilityDetail.link"
            target="_blank"
            style="
              color: #409eff;
              word-break: break-all;
              word-wrap: break-word;
              display: inline-block;
              max-width: 100%;
            "
          >
            {{ vulnerabilityDetail.link }}
          </a>
        </el-descriptions-item>
      </el-descriptions>
      <template #footer>
        <el-button @click="detailDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
.search-form-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.scan-progress {
  p {
    margin: 10px 0;
  }
}
</style>
